








function move(ele, options, fn = function () { }) {
    let count = 0
    for (let key in options) {
        count++
        if (key === 'opacity') options[key] *= 100
        const timer = setInterval(() => {
            let current
            if (key === 'opacity') {
                current = window.getComputedStyle(ele)[key] * 100
            } else {
                current = parseInt(window.getComputedStyle(ele)[key])
            }
            let distance = (options[key] - current) / 10
            distance = distance > 0 ? Math.ceil(distance) : Math.floor(distance)


            if (current === options[key]) {
                clearInterval(timer)
                count--
                if (count === 0) fn()
            } else {
                if (key === "opacity") {
                    ele.style[key] = (current + distance) / 100
                } else {
                    ele.style[key] = current + distance + 'px'
                }
            }
        })
    }
}






// 对象转换成查询字符串方法
function queryStringify(obj) {
    let str = ''

    for (let k in obj) {
        str += k + '=' + obj[k] + '&'
    }

    return str.slice(0, -1)
}

// 封装 ajax 的代码
function ajax(options = {}) {
    // 0. 从 options 内拿到所有的信息, 为了后面验证的时候使用方便
    const { url, method, async, data, headers, dataType, success } = options

    // 1. 验证 options 内的信息
    // 1-1. 验证 options 内的 url 信息是否填写了
    if (!url) throw new Error('url 为必填选项, 请传递此项内容, ^_^')

    // 1-2. 验证 method 信息
    if (!(method === undefined || /^(get|post)$/i.test(method))) throw new Error('method 目前只接受 "GET" 或者 "POST" 方式, 请期待更新 (#^.^#)')

    // 1-3. 验证 async 信息
    if (!(async === undefined || typeof async === 'boolean')) throw new Error('async 需要传递一个 "Boolean" 类型数据呦 O(∩_∩)O哈哈~')

    // 1-4. 验证 data 信息
    if (!(data === undefined || typeof data === 'string' || Object.prototype.toString.call(data) === '[object Object]')) throw new Error('data 需要传递一个 "String" 或者 "Object" 类型数据 o(*￣︶￣*)o')

    // 1-5. 验证 headers 信息
    if (!(headers === undefined || Object.prototype.toString.call(headers) === '[object Object]')) throw new Error('headers 需要传递一个 "Object" 类型数据 o(*￣︶￣*)o')

    // 1-6. 验证 dataType 信息
    if (!(dataType === undefined || /^(json|string)$/i.test(dataType))) throw new Error('dataType 目前只接受 "json" 或者 "string" 两种值')

    // 1-7. 验证 success 信息
    if (!(success === undefined || typeof success === 'function')) throw new Error('success 需要传递一个 "Function" 类型数据')

    // 2. 准备一套默认值
    const _default = {
        url: url,
        method: method || 'GET',
        async: async ?? true,
        data: data || '',
        headers: { 'content-type': 'application/x-www-form-urlencoded', ...headers },
        dataType: dataType || 'string',
        success: success || function () { }
    }
    // 2-1. 调整一下 data 的值
    if (typeof _default.data === 'object') _default.data = queryStringify(_default.data)
    // 2-2. 调整一下 url 的值
    if (/^get$/i.test(_default.method) && _default.data) _default.url += '?' + _default.data

    // 3. 发送请求的代码
    const xhr = new XMLHttpRequest()

    xhr.open(_default.method, _default.url, _default.async)

    xhr.onload = function () {
        // 暂时直接打印结果
        const res = _default.dataType === 'string' ? xhr.responseText : JSON.parse(xhr.responseText)

        // 调用 _default.success 函数
        _default.success(res)
    }

    // 只要 headers 内有内容, 就设置到请求头上
    for (let k in _default.headers) xhr.setRequestHeader(k, _default.headers[k])

        // 分辨一下, 是 get 还是 post 请求
        ; /^get$/i.test(_default.method) ? xhr.send() : xhr.send(_default.data)
}

// 使用 Promise 语法, 对 ajax 进行二次封装
function pAjax(options = {}) {
    // 异步的 ajax 代码
    // 利用 Promise 语法
    const p = new Promise((resolve, reject) => {
        // 书写 ajax 代码

        ajax({
            url: options.url,
            data: options.data,
            async: options.async,
            method: options.method,
            headers: options.headers,
            dataType: options.dataType,
            success(res) {
                // 调用 resolve 让本次 Promise 转换为成功
                resolve(res)
            }
        })
    })

    return p
}
















